/*
**************************************************************************************************************
File:         controller.sv
Description:  Functions as a partial controller - based on inputs, sends signals to interface
Author     :  Katerina Gleeson
**************************************************************************************************************
*/

module controller(input CK, ADDR);
wire [DATA_WIDTH-1:0] data;
wire [ADDR_WIDTH-1:0] addr;
logic [COL_WIDTH-1:0] column;   //7bits 6:0
logic [ROW_WIDTH-1:0] row;      //7bits 13:7 
logic [BANK_ADDR_WIDTH-1:0] bank;

DDR_bus IF;   //need to use interface



always_ff @(posedge CK) begin   //two high signals would be error
	if (write)
		 write();
	else if (read)
		 read();
	else if (nop)
		 nop();
	default: idle();
	endcase
end


always_ff @(posedge CK) begin    //need to refresh at time interval



task is_idle;
	idle();
endtask	


//do we want to implement the startup ZQ calibration commands?

//should the tasks instead pass the address back as a whole, and the interface can accept them as the concatenated portions?


task read(output ref bank, ref column);  
	IF.ENUM.RD <= HIGH;
	column <= addr[COL_WIDTH-1:0];
	bank <= addr[ADDR_WIDTH-1:BANK_END];
	if(row !== addr[BANK_END-1:ROW_END])
	begin
		row <= addr[BANK_END-1:ROW_END];  
		IF.precharge(ref row);
	end
	IF.activate(ref bank, ref row);
	IF.precharge(ref row);		
endtask



task write(output ref bank, ref column);	  
	IF.ENUM.WR <= HIGH;
	column <= addr[COL_WIDTH-1:0];
	bank <= addr[ADDR_WIDTH-1:BANK_END];
	IF.nop();  //no other commands can happen for x cycles

	if(row !== addr[BANK_END-1:ROW_END])  //if different row, need to precharge
	begin
		row <= addr[BANK_END-1:ROW_END];  //not sure if this should be sent separately or in the function
		IF.precharge(ref row);
	end
	IF.activate(ref bank, ref row);
	IF.precharge(ref row);  //assuming open page policy, PRE after WTR	
endtask	
	



//need this? should be asserted after a command so that nothing else can happen during time period
task nop();
	IF.ENUM.NOP <= HIGH;
endtask



task deselect();
	IF.ENUM.DES <= HIGH; 
endtask

